package com.br.aiops.counter;

import com.alibaba.fastjson.JSONArray;
import com.br.aiops.receiver.AlertLog;
import com.br.aiops.rule.Rule;
import com.br.aiops.utils.Constants;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 规则中每个日志的信息统计类
 */
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AlertLogCounter implements Serializable {

    public static final int TIMES_ONE = 1;
    private Rule rule;

    private AlertLog alertLog;
    private Date startTime;
    private Date updateTime;

    //发送告警前的数量，次数告警后清零
    private AtomicInteger alertTimes;
    //该周期内所有告警次数，不清零
    private AtomicInteger alertTimesInAllCycle;

    private Set<String> pods;
    private Set<String> hosts;

    //是否发送过告警
    private Boolean alerted;

    //临时字段，发送告警添加
    private JSONArray allPods;

    /**
     * 对每个alertLog进行统计
     * @param alertLog 日志
     */
    public void count(AlertLog alertLog) {
        //filebeat采集的时间顺序可能不一致
        if (Objects.isNull(startTime) || alertLog.getLogTime().before(startTime)) {
            startTime = alertLog.getLogTime();
        }

        if (Objects.isNull(updateTime) || alertLog.getLogTime().after(updateTime)) {
            updateTime = alertLog.getLogTime();
            this.alertLog = alertLog;
        }

        //非阶梯&压制类型为告警次数&告警次数为1的特殊处理，直接把当前的alertLog赋值，不管顺序；其它的按照上边的逻辑，即获取最后一个alertLog
        if (Objects.equals(rule.getLadderType(), Constants.LADDER_TYPE_NONE)
                && Objects.equals(rule.getJudgeType(), Constants.JUDGE_TYPE_TIMES)
                && Objects.equals(rule.getTimes(), TIMES_ONE)) {
            this.alertLog = alertLog;
        }

        //两部分同时计数
        alertTimes.incrementAndGet();
        alertTimesInAllCycle.incrementAndGet();

        pods.add(alertLog.getPodName());
        //支持多个hosts逗号分隔的情况
        if (alertLog.getHostname().contains(",")) {
            hosts.addAll(Arrays.asList(alertLog.getHostname().split(",")));
        } else {
            hosts.add(alertLog.getHostname());
        }
    }

    /**
     * 是否需要阶梯告警
     * @return 是否需要阶梯告警
     */
    public boolean shouldLadderAlert() {
        return rule.getLadderType() != Constants.LADDER_TYPE_NONE;
    }

    public String counterKey() {
        return alertLog.getService() + "_" + alertLog.getErrorCode() + "_" + rule.getId();
    }
}
